package com.ywh.train;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Vector;
import javax.swing.JFrame;
import my12306.TrainInfoPanel;
import my12306.OrderException;
import my12306.TrainClient;
import my12306.bean.PassengerInfo;
import my12306.bean.QueryResult;
import my12306.bean.Tokens;
import my12306.http.Consts;
import my12306.http.JSONObject;
import my12306.http.TrainInfo;
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 订票逻辑
 *
 * @author cafebabe
 * @since 2011-11-27
 * @version 1.0
 */
public class LogicThread extends Thread {

    private TrainClient trainClient;
    private RobTicket rob;
    private volatile Thread blinker = this;
    private final Logger log = LoggerFactory.getLogger(getClass());

    /**
     * 构造函数
     *
     * @param robTicket
     */
    public LogicThread(TrainClient client, RobTicket rob) {
        this.trainClient = client;
        this.rob = rob;
    }
    private boolean stop = false;
    private final Object waitLock = new Object();
    /*
     * 
     */

    void continueRun() {
        synchronized (waitLock) {
            waitLock.notifyAll();
        }
    }

    private void waitForSignal() {
        synchronized (waitLock) {
            try {
                waitLock.wait();
            } catch (InterruptedException ie) {
                // continue
            }
        }
    }

    public void setDone() {
        stop = true;
        continueRun();
    }

    public void login() {
        //<editor-fold defaultstate="collapsed" desc=" 1. Login "> 
        QueryResult qr;
        int count = 0;
        String loginRand;
        String randCode;
        do {
            try {
                rob.console(MessageFormat.format(ResourceManager.getString("LogicThread.0"), rob.getUsername())); //$NON-NLS-1$
                randCode = trainClient.getRandCodeDailog(Constants.LOGIN_CODE_URL);//弹出识别对话框

                loginRand = trainClient.loginAction_loginAysnSuggest();

                if (loginRand == null || randCode == null || randCode.isEmpty() || loginRand.isEmpty()) {
                    continue;
                }

                qr = trainClient.login(rob.getUsername(), rob.getPassword(), randCode, loginRand);
                if (qr.getState() == QueryResult.SUCC) {
                    rob.console(qr.getMsg());
                } else if (qr.getState() == QueryResult.RAND_CODE_ERROR) {
                    rob.console(Constants.CODE_ERROR);
                    continue;
                } else if (qr.getState() == QueryResult.ACC_ERROR
                        || qr.getState() == QueryResult.PWD_ERROR) {
                    rob.console(Constants.USER_ERR);
                    return;
                } else {
                    rob.console(qr.getMsg());
                }//113,"当前访问用户过多,请重新登录"
                if (trainClient.isLoginOk()) {
                    break;
                } else {
                    Thread.sleep(Config.getSleepTime());
                }
                count++;
            } catch (Exception ex) {
                log.error(ex.getMessage(), ex);
            }
        } while (!trainClient.isLoginOk() && !stop);

//</editor-fold> 
    }

    @Override
    public void run() {
        log.info("Started");
        stop = false;
        while (!stop) {
            try {
                QueryResult qr;
                int count = 0;
                String loginRand;
                String randCode;
                JSONObject json;
                Tokens tokens;

//<editor-fold defaultstate="collapsed" desc=" 1. Login ">                   
                login();

//</editor-fold>  

//<editor-fold defaultstate="collapsed" desc=" 2. query & select seat ">                      

                final HashMap<String, TrainInfo> allTrain = trainClient.querySingleAction_queryLeftTicket(
                        rob.getFromCity(), rob.getToCity(), rob.getStartDate(),
                        rob.getRangDate(), "").getTrains();
                if (allTrain == null) {
                    continue;
                }

                JFrame frame = new JFrame("All Trains");
                List<List<Object>> data = new ArrayList<List<Object>>();
                for (TrainInfo item : allTrain.values()) {
                    data.add(item.toList());
                }
                TrainInfoPanel table = new TrainInfoPanel(data, Consts.columns);
                // MyTable table = new MyTable(allTrain, Constants.columns);
                frame.add(table);
                frame.pack();
                frame.setVisible(true);

                //todo 3 select train
                TrainInfo bestTrain = allTrain.get("G548");   //L32
                List<PassengerInfo> users = rob.getPassengers();
                for (PassengerInfo user : users) {
                    user.setSeatType("O");
                }
                if (!bestTrain.getMeta().isValidate()) {
                    throw new OrderException("此班列车不能预定。");
                }
//</editor-fold>   

//<editor-fold defaultstate="collapsed" desc=" 3. search & book ">                
                while (trainClient.isLoginOk() && !stop) {
                    rob.console(ResourceManager.getString("LogicThread.14"));
                    String id = "" + System.currentTimeMillis();
                    String url;
                    String ticket;
                    String token;

                    //<editor-fold defaultstate="collapsed" desc=" step 1 ">  

//                    do {
//                        randCode = getRandCodeDailog(Constants.ORDER_CODE_URL);
//                        url = "https://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=checkOrderInfo&tFlag=tFlag&rand=";
//                        /*
//                         * "{"checkHuimd":"Y","check608":"Y","msg":"","errMsg":"Y"}"    "{"checkHuimd":"Y","check608":"Y","msg":"","errMsg":"Y"}"
//                         * "{"checkHuimd":"N","check608":"Y","msg":"对不起，由于您取消次数过多，今日将不能继续受理您的订票请求！","errMsg":"Y"}"
//                         */
//                        qr = trainClient.doPost(url + randCode);//
//                        json = new JSONObject(qr.getRawData());
//
//                        if (qr.getState() != QueryResult.SUCC) {
//                            rob.console(qr.getMsg());
//                            continue;
//                        }
//                        if (json.get("msg") == null || json.get("errMsg") == null) {
//                            rob.console("exception, continue");
//                            continue;
//                        } else if (json.get("msg").isEmpty() && json.get("errMsg").equals("Y")) {
//                            break;
//                        } else if (json.get("errMsg").contains("输入的验证码不正确！")) {
//                            rob.console(json.get("errMsg"));
//                            continue;
//                        } else {
//                            rob.console(json.get("msg") + json.get("errMsg"));
//                            throw new OrderException(json.get("msg"));
//                        }
//                    } while (!stop);

                    //step 1-1  post
                    url = "https://dynamic.12306.cn/otsweb/order/querySingleAction.do?method=submutOrderRequest";
                    String refInit = "https://dynamic.12306.cn/otsweb/order/querySingleAction.do?method=init";
                    qr = trainClient.querySingleAction_submutOrderRequest_step1_1("00:00--24:00", bestTrain);
                    trainClient.writetoFile("e:\\test\\" + id + "_1_step1_1", qr.getRawData());

                    if (qr.getState() != QueryResult.SUCC) {
                        rob.console(qr.getMsg());
                        continue;
                    }
                    //step 1-2  get ticket        
                    tokens = trainClient.getTokensFromHtml(qr.getRawData());
//                    tokens = trainClient.getTokensFromUrl();
                    rob.console("ticket" + tokens.getTicket());
                    if (tokens.getTicket() == null || tokens.getTicket().isEmpty()) {
                        rob.console("ticket is empty. please retry.");
                        continue;
                    }
                    rob.console("token" + tokens.getToken());
                    if (tokens.getToken() == null || tokens.getToken().isEmpty()) {
                        rob.console("token is empty. please retry.");
                        continue;
                    }
                    rob.console("bedlevel" + tokens.getBedlevel());
                    if (tokens.getBedlevel() == null || tokens.getBedlevel().isEmpty()) {
                        rob.console("bedlevel is empty. please retry.");
                        continue;
                    }
                    //step 1-3  get token
//                    token = trainClient.getQueryToken();
//                    rob.console("token" + token);
//                    if (token == null || token.isEmpty()) {
//                        rob.console("token is empty. please retry.");
//                        continue;
//                    }

                    //</editor-fold>  

                    //<editor-fold defaultstate="collapsed" desc=" step 2 ">  
                    //step2-1
                    randCode = trainClient.getRandCodeDailog(Constants.ORDER_CODE_URL);
                    url = "https://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=checkOrderInfo&rand=";
//                    qr = trainClient.step2_1(url, randCode, token, ticket, rob.getPassengers(), bestTrain);
                    String refUrl_order = "https://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=init";
                    qr = trainClient.confirmPassengerAction_checkOrderInfo_step2_1(randCode, tokens, users, bestTrain);
                    /*"{"checkHuimd":"Y","check608":"Y","msg":"","errMsg":"Y"}" 
                     * {"checkHuimd":"Y","check608":"Y","msg":"","errMsg":"Y"}                     * 
                     */
                    trainClient.writetoFile("e:\\test\\" + id + "_2_step2_1", qr.getRawData());

                    if (qr.getState() != QueryResult.SUCC) {
                        rob.console(qr.getMsg());
                        continue;
                    }
                    json = new JSONObject(qr.getRawData());
                    if (json.get("msg") == null || !json.get("msg").isEmpty()) {
                        rob.console(json.get("msg"));
                        continue;
                    }

                    //step2-2
                    //https://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=getQueueCount&train_date=2013-01-27&train_no=6300000L3210&station=L32&seat=1&from=GZQ&to=ZZF&ticket=10169030001016900003
                    url = "https://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?";
                    List<NameValuePair> parameters = new ArrayList<NameValuePair>();
                    parameters.add(new BasicNameValuePair("from", bestTrain.getMeta().getFrom_station_telecode()));
                    parameters.add(new BasicNameValuePair("method", "getQueueCount"));
                    parameters.add(new BasicNameValuePair("seat", users.get(0).getSeatType()));
                    parameters.add(new BasicNameValuePair("station", bestTrain.getTrainCode()));//L32
                    parameters.add(new BasicNameValuePair("ticket", tokens.getTicket()));
                    parameters.add(new BasicNameValuePair("to", bestTrain.getMeta().getTo_station_telecode()));
                    parameters.add(new BasicNameValuePair("train_date", bestTrain.getStartDate()));
                    parameters.add(new BasicNameValuePair("train_no", bestTrain.getMeta().getTrainno())); //6300000L3210

                    qr = trainClient.doGet(url + URLEncodedUtils.format(parameters, HTTP.UTF_8));
                    /*"{"countT":0,"count":1132,"ticket":"10000038001000000001","op_1":true,"op_2":false}"  
                     * "{"countT":0,"count":25,"ticket":"10000039561000000000","op_1":true,"op_2":false}"                     * 
                     */
                    trainClient.writetoFile("e:\\test\\" + id + "_2_step2_2", qr.getRawData());

                    if (qr.getState() != QueryResult.SUCC) {
                        rob.console(qr.getMsg());
                        continue;
                    }
                    //</editor-fold>
                    //<editor-fold defaultstate="collapsed" desc=" step 3 ">    

                    //step3-1
                    url = "https://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=confirmSingleForQueueOrder";
                    qr = trainClient.confirmPassengerAction_confirmSingleForQueueOrder_step3_1(randCode, tokens, users, bestTrain);
                    /*"{"errMsg":"非法的订票请求！"}"   
                     * {"errMsg":"Y"}    
                     * "{"errMsg":"包含未付款订单","errCode":"FAIL"}"
                     //"{"errMsg":"排队人数现已超过余票数，请您选择其他席别或车次。","errCode":"MORE"}"
                     */
                    trainClient.writetoFile("e:\\test\\" + id + "_3_step3_1", qr.getRawData());

                    if (qr.getState() != QueryResult.SUCC) {
                        rob.console(qr.getMsg());
                        continue;
                    }
                    json = new JSONObject(qr.getRawData());
                    if (json.get("errMsg") == null) {
                        rob.console("exception, continue");
                        continue;
                    }
                    if (!json.get("errMsg").equals("Y")) {
                        if (json.get("errMsg").contains("排队人数现已超过余票数，请您选择其他席别或车次。")) {
                            rob.console(json.get("errMsg"));
                            continue;
                        } else {
                            rob.console(json.get("errMsg"));
                            throw new OrderException(json.get("errMsg"));
                        }
                    }
                    rob.console("订票成功。");

                    //step3-2
                    url = "https://dynamic.12306.cn/otsweb/order/myOrderAction.do?method=getOrderWaitTime&tourFlag=dc";
                    qr = trainClient.doGet(url);
                    /*"{"tourFlag":"dc","waitTime":-2,"waitCount":0,"requestId":5694723412608919774,"errorcode":"0","msg":"对不起，由于您取消次数过多，今日将不能继续受理您的订票请求。1 月10日您可继续使用订票功能。","count":0}"
                     //"{"tourFlag":"dc","waitTime":-1,"waitCount":0,"orderId":"E412621130","requestId":5694347419390027998,"count":0}" 
                     * "{"tourFlag":"dc","waitTime":-1,"waitCount":0,"orderId":"E463163211","requestId":5694315136385788126,"count":0}"  
                     * "{"tourFlag":"dc","waitTime":-1,"waitCount":0,"orderId":"E463163211","requestId":5694315136385788126,"count":0}"
                     * {"tourFlag":"dc","waitTime":5,"waitCount":0,"requestId":5694285137440123102,"count":0}
                     */
                    trainClient.writetoFile("e:\\test\\" + id + "_3_step3_2", qr.getRawData());

                    if (qr.getState() != QueryResult.SUCC) {
                        rob.console(qr.getMsg());
                        continue;
                    }
                    json = new JSONObject(qr.getRawData());

                    if (json.get("msg") != null) {
                        rob.console(json.get("msg"));
                        throw new OrderException(json.get("msg"));
                    }

                    //step3-3 get order id
                    url = "https://dynamic.12306.cn/otsweb/order/myOrderAction.do?method=getOrderWaitTime&tourFlag=dc";
                    qr = trainClient.doGet(url);
                    //{"tourFlag":"dc","waitTime":-1,"waitCount":0,"orderId":"E431559501","requestId":5694285137440123102,"count":0}
                    json = new JSONObject(qr.getRawData());
                    trainClient.writetoFile("e:\\test\\" + id + "_3_step3_3", qr.getRawData());

                    if (qr.getState() != QueryResult.SUCC) {
                        rob.console(qr.getMsg());
                        continue;
                    }
                    if (json.get("orderId") == null || json.get("orderId").isEmpty()) {
                        rob.console("orderId: is empty");
                    }
                    if (json.get("msg") != null) {
                        rob.console(json.get("msg"));
                        throw new OrderException(json.get("msg"));
                    }
                    //step3-4 payorder
                    //post https://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=payOrder&orderSequence_no=E431559501
                    url = "https://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=payOrder&orderSequence_no=";

//                    qr = trainClient.step3_4(url + json.get("orderId"), refUrl_order, randCode, tokens, rob.getPassengers(), bestTrain);
                    qr = trainClient.confirmPassengerAction_payOrder_step3_4(json.get("orderId"), randCode, tokens, users, bestTrain);
                    //席位已成功锁定，请在<b>45</b>分钟内完成网上支付，否则系统将自动取消本次交易。
                    //"消息提示 系统忙！ 请点击我的订单确认客票的状态后再尝试后续操作。谢谢！"
                    trainClient.writetoFile("e:\\test\\" + id + "_3_step3_4", qr.getRawData());
                    rob.console(qr.getMsg());

                    if (qr.getMsg().contains("席位已成功锁定")) {
                        stop = true;
                        rob.console("席位已成功锁定，请在<b>45</b>分钟内完成网上支付，否则系统将自动取消本次交易。");
                        break;
                    } else if (qr.getMsg().contains("系统忙")) {
                        rob.console("系统忙。");
                        Thread.currentThread().sleep(Config.getSleepTime());
                        continue;
                    } else {
                        rob.console("订票失败，重新开始。");
                        continue;
                    }

                    //</editor-fold>

                }
                //</editor-fold>  

            } catch (Exception ex) {
                log.info("Error: " + ex.getMessage());
                rob.console(ex.getLocalizedMessage());
                log.error(ex.getMessage(), ex);
            } finally {
                rob.console(ResourceManager.getString("LogicThread.22")); //$NON-NLS-1$	
            }
        }
        log.info("Ended");
    }

    /**
     * @return Returns the client.
     */
    public TrainClient getClient() {
        return trainClient;
    }

    /**
     * @param client The client to set.
     */
    public void setClient(TrainClient client) {
        this.trainClient = client;
    }

    /**
     * @param isEnd The isEnd to set.
     */
    public void setEnd(boolean isEnd) {
        blinker = null;
        this.interrupt();
    }
}
